<?php

require("Utils.php");

class ImageManipulator
{

public static function imagecreatefrombmp($p_sFile)
{
	//    Load the image into a string
	$file = fopen($p_sFile,"rb");
	$read = fread($file,10);
	while(!feof($file)&&($read<>""))
		$read .= fread($file,1024);
	$temp = unpack("H*",$read);
	$hex = $temp[1];
	$header = substr($hex,0,108);
	//    Process the header
	//    Structure: http://www.fastgraph.com/help/bmp_header_format.html
	if (substr($header,0,4)=="424d")
	{
		//    Cut it in parts of 2 bytes
		$header_parts = str_split($header,2);
		//    Get the width        4 bytes
		$width = hexdec($header_parts[19].$header_parts[18]);
		//    Get the height        4 bytes
		$height = hexdec($header_parts[23].$header_parts[22]);
		//    Unset the header params
		unset($header_parts);
	}
	//    Define starting X and Y
	$x = 0;
	$y = 1;
	//    Create newimage
	$image = imagecreatetruecolor($width,$height);
	//    Grab the body from the image
	$body = substr($hex,108);
	//    Calculate if padding at the end-line is needed
	//    Divided by two to keep overview.
	//    1 byte = 2 HEX-chars
	$body_size = (strlen($body)/2);
	$header_size = ($width*$height);
	//    Use end-line padding? Only when needed
	$usePadding = ($body_size>($header_size*3)+4);
	//    Using a for-loop with index-calculation instaid of str_split to avoid large memory consumption
	//    Calculate the next DWORD-position in the body
	for ($i=0;$i<$body_size;$i+=3)
	{
		//    Calculate line-ending and padding
		if ($x>=$width)
		{
			//    If padding needed, ignore image-padding
			//    Shift i to the ending of the current 32-bit-block
			if ($usePadding)
				$i += $width%4;
			//    Reset horizontal position
			$x = 0;
			//    Raise the height-position (bottom-up)
			$y++;
			//    Reached the image-height? Break the for-loop
			if ($y>$height)
				break;
		}
		//    Calculation of the RGB-pixel (defined as BGR in image-data)
		//    Define $i_pos as absolute position in the body
		$i_pos = $i*2;
		$r = hexdec($body[$i_pos+4].$body[$i_pos+5]);
		$g = hexdec($body[$i_pos+2].$body[$i_pos+3]);
		$b = hexdec($body[$i_pos].$body[$i_pos+1]);
		//    Calculate and draw the pixel
		$color = imagecolorallocate($image,$r,$g,$b);
		imagesetpixel($image,$x,$height-$y,$color);
		//    Raise the horizontal position
		$x++;
	}
	//    Unset the body / free the memory
	unset($body);
	//    Return image-object
	return $image;
}

public static function IsAnAllowedImage($imagefname)
{
	//static $allowed = array("image/gif","image/jpeg","image/png","image/psd","image/bmp","image/tiff","image/iff","image/vnd.wap.wbmp","image/jp2");
	/*foreach($allowed as $e)
	{
		if($mimetype == $e)
			return TRUE;
	}*/
	$size = getimagesize($imagefname);
	if(imagetypes() & $size[2])
		return TRUE;
	else
		return FALSE;
}

public static function IsAnAllowedImage_Faster($imgtype)
{
	//static $allowed = array("image/gif","image/jpeg","image/png","image/psd","image/bmp","image/tiff","image/iff","image/vnd.wap.wbmp","image/jp2");
	/*foreach($allowed as $e)
	{
		if($mimetype == $e)
			return TRUE;
	}*/
	if($imgtype == IMAGETYPE_BMP)
		return TRUE;
	$imgtypeconv;
	switch($imgtype)
	{
		case IMAGETYPE_GIF: $imgtypeconv = IMG_GIF; break;
		case IMAGETYPE_JPEG: $imgtypeconv = IMG_JPEG; break;
		case IMAGETYPE_PNG: $imgtypeconv = IMG_PNG; break;
		case IMAGETYPE_WBMP: $imgtypeconv = IMG_WBMP; break;
		case IMAGETYPE_XPM: $imgtypeconv = IMG_XPM; break;
	}
	if(imagetypes() & $imgtypeconv)
		return TRUE;
	else
		return FALSE;
}

public static function IsAnAllowedImage_Faster_Mime($imgtype)
{
	//static $allowed = array("image/gif","image/jpeg","image/png","image/psd","image/bmp","image/tiff","image/iff","image/vnd.wap.wbmp","image/jp2");
	/*foreach($allowed as $e)
	{
		if($mimetype == $e)
			return TRUE;
	}*/
	if($imgtype == "image/bmp")
		return TRUE;
	$imgtypeconv;
	switch($imgtype)
	{
		case "image/gif": $imgtypeconv = IMG_GIF; break;
		case "image/jpeg": $imgtypeconv = IMG_JPEG; break;
		case "image/pjpeg": $imgtypeconv = IMG_JPEG; break;
		case "image/png": $imgtypeconv = IMG_PNG; break;
		case "image/vnd.wap.wbmp": $imgtypeconv = IMG_WBMP; break;
		case "image/xbm": $imgtypeconv = IMG_XBM; break;
		case "image/xpm": $imgtypeconv = IMG_XPM; break;
	}
	if((imagetypes() & $imgtypeconv) > 0)
		return TRUE;
	else
		return FALSE;
}

public static function OptimizeImageForFlash(&$filename,&$publicfilename,$maxsize = NULL)
{
	$size = getimagesize($filename);
	$oldfilename = $filename;
	if($size)
	{
		$image = NULL;
		try
		{
			if($maxsize && ($size[0] > $maxsize[0] || $size[1] > $maxsize[1]))
			{
				switch($size[2])
				{
					case IMAGETYPE_GIF:
						$image = imagecreatefromgif($filename); break;
					case IMAGETYPE_JPEG:
						$image = imagecreatefromjpeg($filename); break;
					case IMAGETYPE_PNG:
						$image = imagecreatefrompng($filename); break;
					case IMAGETYPE_BMP:
						$image = ImageManipulator::imagecreatefrombmp($filename); break;
					case IMAGETYPE_WBMP:
						$image = imagecreatefromwbmp($filename); break;
					case IMAGETYPE_XBM:
						$image = imagecreatefromxbm($filename); break;
					case IMAGETYPE_XPM:
						$image = imagecreatefromxpm($filename); break;
					default:
					{
						unlink($oldfilename);
						return FALSE;
					}
				}
			}
			else
			{
				switch($size[2])
				{
					case IMAGETYPE_GIF:
					case IMAGETYPE_JPEG:
					case IMAGETYPE_PNG:
						return TRUE; break;
					case IMAGETYPE_BMP:
						$image = ImageManipulator::imagecreatefrombmp($filename); break;
					case IMAGETYPE_WBMP:
						$image = imagecreatefromwbmp($filename); break;
					case IMAGETYPE_XBM:
						$image = imagecreatefromxbm($filename); break;
					case IMAGETYPE_XPM:
						$image = imagecreatefromxpm($filename); break;
					default:
					{
						unlink($oldfilename);
						return FALSE;
					}
				}
			}
		}
		catch(Exception $e)
		{
			unlink($oldfilename);
			return FALSE;
		}
		if($maxsize != NULL)
		{
			$newsx = $size[0];
			$newsy = $size[1];
			if($newsx > $maxsize[0])
			{
				$cf = $maxsize[0]/$newsx;
				$newsx *= $cf;
				$newsy *= $cf;
			}
			if($newsy > $maxsize[1])
			{
				$cf = $maxsize[1]/$newsy;
				$newsx *= $cf;
				$newsy *= $cf;
			}
			if($newsx != $size[0] || $newsy != $size[1])
			{
				$newimg = imagecreatetruecolor($newsx, $newsy);
				if(imagecopyresized($newimg,$image,0,0,0,0,$newsx,$newsy,$size[0],$size[1]))
				{
					imagedestroy($image);
					$image = $newimg;
				}
			}
		}
		$filename = Utils::change_extension($filename,"png");
		$publicfilename = Utils::change_extension($publicfilename,"png");
		if(imagepng($image,$filename))
		{
			unlink($oldfilename);
			return TRUE;
		}
		else
		{
			unlink($oldfilename);
			return FALSE;
		}
	}
	else
	{
		unlink($oldfilename);
		return FALSE;
	}
}

public static function SaveUploadedImage($tmppath,$initName,$dir,$optimizeForFlash,$optimizationMaxSize,$createThumbnail)
{
	$finalfname = getcwd() . "/" . $dir . $initName;
	if(!file_exists(getcwd() . "/" . $dir))
		mkdir(getcwd() . "/" . $dir);
	$finalpublicname = $dir . $initName;
	$rep_id = 1;
	while(file_exists($finalfname))
	{
		$finalfname = getcwd() . "/" . $dir . "r" . $rep_id . $initName;
		$finalpublicname = $dir . "r" . $rep_id . $initName;
		$rep_id++;
	}
	if(!move_uploaded_file($tmppath, $finalfname))
		return FALSE;
	else
	{
		$success = TRUE;
		if($optimizeForFlash)
			$success = ImageManipulator::OptimizeImageForFlash($finalfname,$finalpublicname,$optimizationMaxSize);
		if($createThumbnail && $success)
			$success = ImageManipulator::CreateThumbnail($finalfname);
		return ($success) ? $finalpublicname : FALSE;
	}
}

public static function CreateThumbnail($filename,$ThumbnailSize)//$ThumbnailSize = 128.0
{
	$size = getimagesize($filename);
	if($size)
	{
		$image = NULL;
		try
		{
			switch($size[2])
			{
				case IMAGETYPE_GIF:
					$image = imagecreatefromgif($filename); break;
				case IMAGETYPE_JPEG:
					$image = imagecreatefromjpeg($filename); break;
				case IMAGETYPE_PNG:
					$image = imagecreatefrompng($filename); break;
				case IMAGETYPE_BMP:
					$image = ImageManipulator::imagecreatefrombmp($filename); break;
				case IMAGETYPE_WBMP:
					$image = imagecreatefromwbmp($filename); break;
				case IMAGETYPE_XBM:
					$image = imagecreatefromxbm($filename); break;
				case IMAGETYPE_XPM:
					$image = imagecreatefromxpm($filename); break;
				default:
				{
					unlink($filename);
					return FALSE;
				}
			}
		}
		catch(Exception $e)
		{
			unlink($filename);
			return FALSE;
		}
		$tfilename = Utils::change_extension($filename,"_thumb_.png");
		$w = $size[0];
		$h = $size[1];
		$m = $ThumbnailSize/max($w,$h);
		$w *= $m;
		$h *= $m;
		$thumb = imagecreatetruecolor($ThumbnailSize, $ThumbnailSize);
		$basecolor = imagecolorallocate($thumb, 255, 255, 255);//bianco trasparente
		imagefill($thumb,0,0,$basecolor);
		imagecolortransparent($thumb,$basecolor);
		imagecopyresized($thumb,$image,($ThumbnailSize-$w)/2,($ThumbnailSize-$h)/2,0,0,$w,$h,$size[0],$size[1]);
		if(imagepng($thumb,$tfilename))
		{
			imagedestroy($image);
			imagedestroy($thumb);
			return TRUE;
		}
		else
		{
			imagedestroy($image);
			imagedestroy($thumb);
			unlink($filename);
			return FALSE;
		}
	}
	else
	{
		unlink($filename);
		return FALSE;
	}
}

public static function LoadImageWithType($filename,$type)
{
	$image = NULL;
	try
	{
		switch($type)
		{
			case IMAGETYPE_GIF:
				$image = imagecreatefromgif($filename); break;
			case IMAGETYPE_JPEG:
				$image = imagecreatefromjpeg($filename); break;
			case IMAGETYPE_PNG:
				$image = imagecreatefrompng($filename); break;
			case IMAGETYPE_BMP:
				$image = ImageManipulator::imagecreatefrombmp($filename); break;
			case IMAGETYPE_WBMP:
				$image = imagecreatefromwbmp($filename); break;
			case IMAGETYPE_XBM:
				$image = imagecreatefromxbm($filename); break;
			case IMAGETYPE_XPM:
				$image = imagecreatefromxpm($filename); break;
			default:
				return FALSE;
		}
	}
	catch(Exception $e)
	{
		return FALSE;
	}
	return $image;
}

public static function LoadImage($filename)
{
	$size = getimagesize($filename);
	if(!$size)
		return FALSE;
	$image = NULL;
	try
	{
		switch($size[2])
		{
			case IMAGETYPE_GIF:
				$image = imagecreatefromgif($filename); break;
			case IMAGETYPE_JPEG:
				$image = imagecreatefromjpeg($filename); break;
			case IMAGETYPE_PNG:
				$image = imagecreatefrompng($filename); break;
			case IMAGETYPE_BMP:
				$image = ImageManipulator::imagecreatefrombmp($filename); break;
			case IMAGETYPE_WBMP:
				$image = imagecreatefromwbmp($filename); break;
			case IMAGETYPE_XBM:
				$image = imagecreatefromxbm($filename); break;
			case IMAGETYPE_XPM:
				$image = imagecreatefromxpm($filename); break;
			default:
				return FALSE;
		}
	}
	catch(Exception $e)
	{
		return FALSE;
	}
	return $image;
}

public static function SaveImage($img,$filename,$type)
{
	try
	{
		switch($type)
		{
			case IMAGETYPE_GIF:
				return imagegif($img,$filename);
			case IMAGETYPE_JPEG:
				return imagejpeg($img,$filename);
			case IMAGETYPE_PNG:
				return imagepng($img,$filename);
			case IMAGETYPE_BMP:
				return FALSE;
			case IMAGETYPE_WBMP:
				return imagewbmp($img,$filename);
			case IMAGETYPE_XBM:
				return FALSE;
			case IMAGETYPE_XPM:
				return FALSE;
			default:
				return FALSE;
		}
	}
	catch(Exception $e)
	{
		return FALSE;
	}
}

//adatta la grandezza ($logoxlen,$logoylen) nel riquadro (($xbs,$ybs),($xbe,$ybe)) e immette il risultato del riquadro con posizione del vertice alto-sinistro in ($xls,$yls) e grandezza in ($xlen,$ylen)
private static function adapt($xbs, $ybs, $xbe, $ybe, $logoxlen, $logoylen, &$xls, &$yls, &$xlen, &$ylen)
{
	$bound_sizex = $xbe-$xbs;
	$bound_sizey = $ybe-$ybs;
	if($bound_sizex*$logoylen/$logoxlen > $bound_sizey)
	{
		$xlen = $bound_sizey*$logoxlen/$logoylen;
		$ylen = $bound_sizey;
	}
	else
	{
		$ylen = $bound_sizex*$logoylen/$logoxlen;
		$xlen = $bound_sizex;
	}
	$xls = ($xbs+$xbe)/2-$xlen/2;
	$yls = ($ybs+$ybe)/2-$ylen/2;
}

//define('BOTTOM_ANCHOR',(int)1);
//define('TOP_ANCHOR',2);
//define('LEFT_ANCHOR',(int)4);
//define('RIGHT_ANCHOR',(int)8);
const BOTTOM_ANCHOR = 1;
const TOP_ANCHOR = 2;
const LEFT_ANCHOR = 4;
const RIGHT_ANCHOR = 8;

public static function MergePhotos($imagefilebase,$imagefiletoplace,$xstart,$ystart,$xending,$yending,$percent = TRUE,$maintain_aspect_ratio = TRUE,$anchor = 0)
{
	//caricamento immagine base
	$size = getimagesize($imagefilebase);
	if(!$size)
		return FALSE;
	$image = ImageManipulator::LoadImageWithType($imagefilebase,$size[2]);
	if(!$image)
		return FALSE;
	//caricament immagine marchio
	$size2 = getimagesize($imagefiletoplace);
	if(!$size2)
	{
		return FALSE;
		imagedestroy(image);
	}
	$image2 = ImageManipulator::LoadImageWithType($imagefiletoplace,$size2[2]);
	if(!$image)
	{
		return FALSE;
		imagedestroy(image);
	}
	//calcoli di grandezza
	if($percent)
	{
		$xs = ($xstart/100.0)*$size[0];
		$ys = ($ystart/100.0)*$size[1];
		$xe = ($xending/100.0)*$size[0];
		$ye = ($yending/100.0)*$size[1];
		$xl = $xe-$xs;
		$yl = $ye-$ys;
		if($maintain_aspect_ratio)
		{
			$xs_tmp = 0;
			$ys_tmp = 0;
			ImageManipulator::adapt($xs,$ys,$xe,$ye,$size2[0],$size2[1],$xs_tmp,$ys_tmp,$xl,$yl);
			if($xs != $xs_tmp)
			{
				if($anchor & ImageManipulator::LEFT_ANCHOR)
					$xs_tmp = $xs;
				if($anchor & ImageManipulator::RIGHT_ANCHOR)
					$xs_tmp = $xe-$xl;
			}
			if($ys != $ys_tmp)
			{
				if($anchor & ImageManipulator::TOP_ANCHOR)
					$ys_tmp = $ys;
				if($anchor & ImageManipulator::BOTTOM_ANCHOR)
					$ys_tmp = $ye-$yl;
			}
			$xs = $xs_tmp;
			$ys = $ys_tmp;
		}
	}
	else
	{
		$xs = $xstart;
		$ys = $ystart;
		$xl = $xending-$xs;
		$yl = $yending-$ys;
	}
	if(!imagecopyresampled($image,$image2,$xs,$ys,0,0,$xl,$yl,$size2[0],$size2[1]))
	{
		imagedestroy($image);
		imagedestroy($image2);
		return FALSE;
	}
	else
	{
		$tmpname = Utils::change_extension($imagefilebase,".tmp".Utils::get_extension($imagefilebase));
		if(ImageManipulator::SaveImage($image,$tmpname,$size[2]))
		{
			unlink($imagefilebase);
			rename($tmpname,$imagefilebase);
			return TRUE;
		}
		else
			return FALSE;
	}
}

}

?>